package com.ruoyi.reception;

import com.ruoyi.common.constant.RedisConstants;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.exception.CustomException;
import com.ruoyi.common.utils.IdWorker;
import com.ruoyi.common.utils.MapCheckUtil;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.receipt.domain.TbCaManager;
import com.ruoyi.receipt.domain.TbCaUser;
import com.ruoyi.receipt.domain.TbUser;
import com.ruoyi.receipt.domain.TbUserRelation;
import com.ruoyi.receipt.service.ITbCaManagerService;
import com.ruoyi.receipt.service.ITbCaUserService;
import com.ruoyi.receipt.service.ITbUserRelationService;
import com.ruoyi.receipt.service.ITbUserService;
import com.ruoyi.receipt.service.impl.ALSmsSendServiceImpl;
import com.ruoyi.receipt.utils.CurrentUserUtils;
import com.ruoyi.receipt.utils.JwtUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 用户信息Controller
 * 
 * @author ruoyi
 * @date 2021-03-15
 */
@RestController
@RequestMapping("/reception/user")
public class TbUserRecController extends BaseController
{

    @Autowired
    private ITbUserService tbUserService;

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private ALSmsSendServiceImpl aLSmsSendServiceImpl;

    @Autowired
    private ITbCaUserService tbCaUserService;

    @Autowired
    private ITbCaManagerService tbCaManagerService;

    @Autowired
    private ITbUserRelationService tbUserRelationService;

    @Autowired
    private JwtUtils jwtUtils;

    /**
     * 根据账号密码进行登录
     */
    @PostMapping("/loginByPwdAndAccount")
    public AjaxResult loginByPwdAndAccount(@RequestBody Map map) {

        MapCheckUtil.requiredCheck(map,new String[]{"loginAccount","type","pwd"});

        //获取登录账号
        String loginAccount = map.get("loginAccount")+"";

        //获取pwd
        String pwd=map.get("pwd")+"";

        //获取type
        String type=map.get("type")+"";

        TbUser tempBaseUser=new TbUser();
        tempBaseUser.setLoginAccount(loginAccount);
        tempBaseUser.setIsDel(0);
        tempBaseUser.setType(Integer.parseInt((type)));

        List<TbUser> tbUserList = tbUserService.selectTbUserList(tempBaseUser);
        if(tbUserList.size()==0){
            throw new CustomException("未查询出当前用户",2006);
        }

        TbUser tbUserDb=tbUserList.get(0);

        //将用户输入的密码和数据库中的密码进行比对
        if (!SecurityUtils.matchesPassword(pwd, tbUserDb.getPwd()))
        {
            throw new CustomException("用户名或密码错误",2003);
        }

        Map resultMap=new HashMap();
        resultMap.put("token",cacheUserToRedis(tbUserDb));
        return AjaxResult.success(resultMap);
    }

    /**
     * 检查注册验证码是否正确
     */
    public boolean checkVerCode(@RequestBody Map map) {

        //获取登录账号
        String loginAccount = map.get("loginAccount")+"";

        //获取code
        String code=map.get("code")+"";

        Boolean codeFlag=aLSmsSendServiceImpl.checkVerCode(loginAccount,code);

        return codeFlag;
    }

    /**
     * 检查修改手机号验证码是否正确
     */
    public boolean checkUpdatePhone(@RequestBody Map map) {

        //获取登录账号
        String loginAccount = map.get("updatePhone")+"";

        //获取code
        String code=map.get("code")+"";

        Boolean codeFlag=aLSmsSendServiceImpl.checkUpdatePhoneCode(loginAccount,code);

        return codeFlag;
    }

    /**
     * 检查注册验证码是否正确
     */
    @PostMapping("/checkVerCodeReq")
    public AjaxResult checkVerCodeReq(@RequestBody Map map) {

        boolean flag= checkVerCode(map);
        if(flag){
            return AjaxResult.success(flag);
        }else{
            throw new CustomException("验证码错误",2001);
        }
    }

    /**
     * 检查修改手机号验证码是否正确
     */
    @PostMapping("/checkUpdatePhoneReq")
    public AjaxResult checkUpdatePhoneReq(@RequestBody Map map) {
        boolean flag= checkUpdatePhone(map);
        if(flag){
            return AjaxResult.success(flag);
        }else{
            throw new CustomException("验证码错误",2001);
        }
    }

    /**
     * 注册或登录用户
     */
    @PostMapping("/loginAndRegist")
    public AjaxResult logon(@RequestBody Map map) {

        Boolean checkCodeFlag=checkVerCode(map);
        if(!checkCodeFlag){
            return AjaxResult.error("验证码错误",2001);
        }


        Map resultMap=new HashMap();

        MapCheckUtil.requiredCheck(map,new String[]{"loginAccount","type","deviceId"});

        //获取登录账号
        String loginAccount = map.get("loginAccount")+"";

        //获取type
        String type=map.get("type")+"";

        //获取deviceId
        String deviceId=map.get("deviceId")+"";

        //获取pwd
        String pwd=map.get("pwd")+"";

        TbUser tempBaseUser=new TbUser();
        tempBaseUser.setLoginAccount(loginAccount);
        tempBaseUser.setIsDel(0);
        tempBaseUser.setType(Integer.parseInt((type)));
        tempBaseUser.setPwd(pwd);

        //先判断是否为新用户,新用户的话直接走注册即可
        Map findLoginAccountInfoMap = tbUserService.findLoginAccountInfo(loginAccount, type);

        //角色数量
        Integer typeNumber=Integer.parseInt(findLoginAccountInfoMap.get("typeNumber")+"");

        //是否存在 true为存在 false为不存在
        Boolean isExist= (Boolean) findLoginAccountInfoMap.get("isExist");

        //根据loginAccount+type查询出的数据库对象
        TbUser resultUser= (TbUser) findLoginAccountInfoMap.get("tbUser");

        if(!isExist){

            //进行注册
            TbUser tbUserResult=tbUserService.registNewUser(map);

            //清空resultMap中的所有数据
            resultMap.clear();

            //获取到用户token
            resultMap.put("token",cacheUserToRedis(tbUserResult));
            //登陆成功后,修改deviceId
            tbUserService.updateDeviceId(tbUserResult.getId(),deviceId);
            return AjaxResult.success(resultMap);
        }

        //查询是否需要重置,重置的话删除了密码和密保
        //登陆后直接颁发token
        if(resultUser.getIsReset()==1){
            //清空resultMap中的所有数据
            resultMap.clear();

            //获取到用户token
            resultMap.put("token",cacheUserToRedis(resultUser));
            //登陆成功后,修改deviceId
            tbUserService.updateDeviceId(resultUser.getId(),deviceId);
            return AjaxResult.success(resultMap);
        }

        //如果登陆账号大于一种角色时,都需要输入账号密码进行登录
        if(typeNumber>1){
            Map mapTemp = login(tempBaseUser);
            String token=mapTemp.get("token")+"";
            TbUser tbUserResult= (TbUser) mapTemp.get("tbUser");

            //清空resultMap中的所有数据
            resultMap.clear();

            //获取到用户token
            resultMap.put("token",mapTemp.get("token")+"");
            //登陆成功后,修改deviceId
            tbUserService.updateDeviceId(tbUserResult.getId(),deviceId);
            return AjaxResult.success(resultMap);
        }

        //如果登录只有一种角色,并且为学生(2)的话
        //验证码通过后直接登录
        if(typeNumber==1&&type.equals("2")){

            //获取到用户token
            resultMap.put("token",cacheUserToRedis(resultUser));
            //登陆成功后,修改deviceId
            tbUserService.updateDeviceId(resultUser.getId(),deviceId);
            return AjaxResult.success(resultMap);

        }

        //家长的旧设备+验证码直接登录
        if((type.equals("1")&&deviceId.equals(resultUser.getDeviceId()))){

            //获取到用户token
            resultMap.put("token",cacheUserToRedis(resultUser));
            //登陆成功后,修改deviceId
            tbUserService.updateDeviceId(resultUser.getId(),deviceId);
            return AjaxResult.success(resultMap);
        }

        //家长的新设备登录
        //验证码+账号
        if((type.equals("1")&&!deviceId.equals(resultUser.getDeviceId()))){

            Map mapTemp = login(tempBaseUser);
            String token=mapTemp.get("token")+"";
            TbUser tbUserResult= (TbUser) mapTemp.get("tbUser");

            //清空resultMap中的所有数据
            resultMap.clear();

            //获取到用户token
            resultMap.put("token",mapTemp.get("token")+"");
            //登陆成功后,修改deviceId
            tbUserService.updateDeviceId(tbUserResult.getId(),deviceId);
            return AjaxResult.success(resultMap);

        }

        return AjaxResult.success();
    }

    /**
     * 重置密码并设置密保
     */
    @PostMapping("/resetCaAndPwd")
    public AjaxResult checkPwdAndCa(@RequestBody Map map){

        String pwd=map.get("pwd")+"";
        String qPwd=map.get("qPwd")+"";
        if(!pwd.equals(qPwd)){
            throw new CustomException("两次密码不一致",2004);
        }

        TbUser currentUser = CurrentUserUtils.getCurrentUser();

        TbUser tbUser = tbUserService.selectTbUserById(currentUser.getId());
        tbUser.setIsReset(0);
        tbUser.setPwd(SecurityUtils.encryptPassword(pwd));

        tbUserService.updateTbUser(tbUser);

        //新增密保问题
        tbUserService.setCaByUserId(tbUser.getId(),map);

        return AjaxResult.success();
    }

    /**
     * 检查密码和密保设否需要重新设置
     */
    @PostMapping("/checkPwdAndCa")
    public AjaxResult checkPwdAndCa(TbUser tbuser){
            //检查是否设置过密码
            boolean isSetPwd=false;

            //检查是否设置过密保
            boolean isSetCa=false;

            TbUser tbUserDb = tbUserService.selectTbUserById(tbuser.getId());

            //查看是否设置过密码
            if(!StringUtils.isEmpty(tbUserDb.getPwd())){
                isSetPwd=true;
            }

            //查看密保是否设置
            TbCaUser tbCaUser=new TbCaUser();
            tbCaUser.setIsDel(0);
            tbCaUser.setUserId(tbuser.getId());

            if(tbCaUserService.selectTbCaUserList(tbCaUser).size()>0){
                isSetCa=true;
            }

            Map resultMap=new HashMap();
            resultMap.put("isSetPwd",isSetPwd);
            resultMap.put("isSetCa",isSetCa);

            return AjaxResult.success(resultMap);
    }

    /**
     * 查询登录账号信息
     */
    @PostMapping("/findLoginAccountInfo")
    public AjaxResult findLoginAccountInfo(@RequestBody Map map) {

        //先判断是否为新用户,新用户的话直接走注册即可
        Map findLoginAccountInfoMap = tbUserService.findLoginAccountInfo(map.get("loginAccount")+"",map.get("type")+"");

        //角色数量
        Integer typeNumber=Integer.parseInt(findLoginAccountInfoMap.get("typeNumber")+"");

        //是否存在 true为存在 false为不存在
        Boolean isExist= (Boolean) findLoginAccountInfoMap.get("isExist");

        //根据loginAccount+type查询出的数据库对象
        TbUser resultUser= (TbUser) findLoginAccountInfoMap.get("tbUser");

        Integer isReset=0;

        Integer userRelation=0;

        //设备码
        String deviceId="";

        //是否设置基本信息
        boolean isSetBaseInfo=true;

        if(null!=resultUser){

            isReset=resultUser.getIsReset();

            deviceId=resultUser.getDeviceId();

            if(StringUtils.isEmpty(resultUser.getRealName())){
                isSetBaseInfo=false;
            }

            TbUserRelation tbUserRelation=new TbUserRelation();

            if((map.get("type")+"").equals("1")){
                tbUserRelation.setParentId(resultUser.getId());
                tbUserRelation.setIsDel(0);
            }

            if((map.get("type")+"").equals("2")){
                tbUserRelation.setChildId(resultUser.getId());
                tbUserRelation.setIsDel(0);
            }

            userRelation=tbUserRelationService.selectTbUserRelationList(tbUserRelation).size();

        }

        Map resultMap=new HashMap();
        resultMap.put("typeNumber",typeNumber);
        resultMap.put("isExist",isExist);
        resultMap.put("isReset",null==isReset?0:isReset);
        //查询绑定关系
        resultMap.put("userRelation",userRelation);
        //设备id
        resultMap.put("deviceId",deviceId);
        //是否设置基本信息
        resultMap.put("isSetBaseInfo",isSetBaseInfo);


        return AjaxResult.success(resultMap);
    }

    /**
     * 修改手机号
     */
    @PostMapping("/updatePhone")
    public AjaxResult updatePhone(@RequestBody Map map) {


        TbUser currentUser = CurrentUserUtils.getCurrentUser();

        Boolean checkCodeFlag=checkUpdatePhone(map);
        if(!checkCodeFlag){
            return AjaxResult.error("验证码错误",2001);
        }

        //修改的手机号
        String updatePhone=map.get("updatePhone")+"";

        TbUser tempUser=new TbUser();
        tempUser.setLoginAccount(updatePhone);
        tempUser.setIsDel(0);

        //查询修改的手机号是否存在
        List<TbUser> tbUsersList = tbUserService.selectTbUserList(tempUser);
        if(tbUsersList.size()>0){
            throw new CustomException("手机号已被绑定",2005);
        }

        TbUser tbUser=new TbUser();
        tbUser.setId(currentUser.getId());
        tbUser.setOldLoginAccount(tempUser.getLoginAccount());
        tbUser.setLoginAccount(updatePhone);
        tbUser.setIsDel(0);
        tbUserService.updateTbUser(tbUser);

        return AjaxResult.success("修改成功");
    }

    /**
     * 根据旧密码修改新密码
     */
    @PostMapping("/updatePwdByOldPwd")
    public AjaxResult updatePwdByOldPwd(@RequestBody Map map) {

        Long userId=CurrentUserUtils.getCurrentUser().getId();

        //旧密码
        String oldPwd=map.get("oldPwd")+"";

        //新密码
        String newPwd=map.get("newPwd")+"";

        //确认密码
        String qNewPwd=map.get("qNewPwd")+"";

        TbUser dbTbUSer = tbUserService.selectTbUserById(userId);

        if(!SecurityUtils.matchesPassword(oldPwd,dbTbUSer.getPwd())){
            throw new CustomException("密码错误",2003);
        }

        if(!newPwd.equals(qNewPwd)){
            throw new CustomException("两次密码不一致",2004);
        }

        dbTbUSer.setPwd(SecurityUtils.encryptPassword(newPwd));
        tbUserService.updateTbUser(dbTbUSer);

        return AjaxResult.success("修改成功");
    }

    /**
     * 修改密码
     */
    @PostMapping("/updatePwd")
    public AjaxResult updatePwd(@RequestBody Map map) {

        TbUser tbUser=new TbUser();
        tbUser.setLoginAccount(map.get("loginAccount")+"");
        tbUser.setType(Integer.parseInt(map.get("type")+""));
        tbUser.setIsDel(0);

        List<TbUser> tbUserList=tbUserService.selectTbUserList(tbUser);
        if(tbUserList.size()==0){
            throw new CustomException("未查询出当前用户",2006);
        }

        //获取第一个查询出的用户
        TbUser dbUser=new TbUser();
        if(tbUserList.size()>0){
            dbUser=tbUserList.get(0);
        }

        String pwd=map.get("pwd")+"";
        String qPwd=map.get("qPwd")+"";
        if(!pwd.equals(qPwd)){
            throw new CustomException("两次密码不一致",2004);
        }

        dbUser.setPwd(SecurityUtils.encryptPassword(pwd));

        tbUserService.updateTbUser(dbUser);

        return AjaxResult.success("修改成功");
    }

    /**
     * 根据密保修改密码
     */
    @PostMapping("/updatePwdByCa")
    public AjaxResult updatePwdByCa(@RequestBody Map map) {

        TbUser tbUser=new TbUser();
        tbUser.setLoginAccount(map.get("loginAccount")+"");
        tbUser.setType(Integer.parseInt(map.get("type")+""));
        tbUser.setIsDel(0);

        List<TbUser> tbUserList=tbUserService.selectTbUserList(tbUser);
        if(tbUserList.size()==0){
            throw new CustomException("未查询出当前用户",2006);
        }

        //获取第一个查询出的用户
        TbUser dbUser=new TbUser();
        if(tbUserList.size()>0){
            dbUser=tbUserList.get(0);
        }

        //判断密保问题是否正确
        Boolean flag=tbCaUserService.checkUserCa(map,dbUser);

        if(!flag){
               throw new CustomException("密保问题错误",2007);
        }

        String pwd=map.get("pwd")+"";
        String qPwd=map.get("qPwd")+"";
        if(!pwd.equals(qPwd)){
            throw new CustomException("两次密码不一致",2004);
        }

        dbUser.setPwd(SecurityUtils.encryptPassword(pwd));

        tbUserService.updateTbUser(dbUser);

        return AjaxResult.success("修改成功");
    }

    /**
     * 查询密保问题是否正确
     */
    @PostMapping("/selectCaIsRight")
    public AjaxResult selectCaIsRight(@RequestBody Map map) {

        TbUser tbUser=new TbUser();
        tbUser.setLoginAccount(map.get("loginAccount")+"");
        tbUser.setType(Integer.parseInt(map.get("type")+""));
        tbUser.setIsDel(0);

        List<TbUser> tbUserList=tbUserService.selectTbUserList(tbUser);
        if(tbUserList.size()==0){
            throw new CustomException("未查询出当前用户",2006);
        }

        //获取第一个查询出的用户
        TbUser dbUser=new TbUser();
        if(tbUserList.size()>0){
            dbUser=tbUserList.get(0);
        }

        //判断密保问题是否正确
        Boolean flag=tbCaUserService.checkUserCa(map,dbUser);

        if(!flag){
            throw new CustomException("密保问题错误",2007);
        }

        return AjaxResult.success();
    }

    /**
     * 根据登录账号修改密码
     */
    @PostMapping("/updatePwdByLoginAccount")
    public AjaxResult updatePwdByLoginAccount(@RequestBody Map map) {

        TbUser tbUser=new TbUser();
        tbUser.setLoginAccount(map.get("loginAccount")+"");
        tbUser.setType(Integer.parseInt(map.get("type")+""));
        tbUser.setIsDel(0);

        List<TbUser> tbUserList=tbUserService.selectTbUserList(tbUser);
        if(tbUserList.size()==0){
            throw new CustomException("未查询出当前用户",2006);
        }

        //获取第一个查询出的用户
        TbUser dbUser=new TbUser();
        if(tbUserList.size()>0){
            dbUser=tbUserList.get(0);
        }

        String pwd=map.get("pwd")+"";
        String qPwd=map.get("qPwd")+"";
        if(!pwd.equals(qPwd)){
            throw new CustomException("两次密码不一致",2004);
        }

        dbUser.setPwd(SecurityUtils.encryptPassword(pwd));

        tbUserService.updateTbUser(dbUser);

        return AjaxResult.success("修改成功");
    }

    /**
     * 查询当前用户密保问题
     */
    @PostMapping("/selectCurrentUserCa")
    public AjaxResult selectCurrentUserCa() {

        Map resultMap=new HashMap();

        Long userId=CurrentUserUtils.getCurrentUser().getId();

        TbCaUser tbCaUser =new TbCaUser();
        tbCaUser.setUserId(userId);

        List<TbCaUser> tbCaUsers = tbCaUserService.selectTbCaUserList(tbCaUser);

        for (int i = 0; i < tbCaUsers.size(); i++) {
            TbCaManager tbCaManager = tbCaManagerService.selectTbCaManagerById(tbCaUsers.get(i).getCaManagerId());
            resultMap.put("ca"+(i+1),tbCaManager);
        }

        return AjaxResult.success(resultMap);
    }

    /**
     * 查询当前用户密保问题,未登录状态
     */
    @PostMapping("/selectCurrentUserCaUnLogin")
    public AjaxResult selectCurrentUserCaUnLogin(@RequestBody Map map) {
        TbUser tbUser=new TbUser();
        tbUser.setLoginAccount(map.get("loginAccount")+"");
        tbUser.setType(Integer.parseInt(map.get("type")+""));
        tbUser.setIsDel(0);

        List<TbUser> tbUserList=tbUserService.selectTbUserList(tbUser);
        if(tbUserList.size()==0){
            throw new CustomException("未查询出当前用户",2006);
        }

        //获取第一个查询出的用户
        TbUser dbUser=new TbUser();
        if(tbUserList.size()>0){
            dbUser=tbUserList.get(0);
        }

        Long userId=dbUser.getId();

        TbCaUser tbCaUser =new TbCaUser();
        tbCaUser.setUserId(userId);

        List<TbCaUser> tbCaUsers = tbCaUserService.selectTbCaUserList(tbCaUser);

        Map resultMap=new HashMap();

        for (int i = 0; i < tbCaUsers.size(); i++) {
            TbCaManager tbCaManager = tbCaManagerService.selectTbCaManagerById(tbCaUsers.get(i).getCaManagerId());
            resultMap.put("ca"+(i+1),tbCaManager);
        }

        return AjaxResult.success(resultMap);

    }

    //根据登录账号和密码查询用户信息,生成token
    public Map login(TbUser tbUser)
    {
        if(null==tbUser.getLoginAccount()||null==tbUser.getPwd()){
            throw new CustomException("请确认信息完整");
        }

        //查询出数据库中的用户信息
        TbUser tbUserTemp=new TbUser();
        tbUserTemp.setLoginAccount(tbUser.getLoginAccount());
        tbUserTemp.setType(tbUser.getType());
        tbUserTemp.setIsDel(0);
        List<TbUser> tbUserList=tbUserService.selectTbUserList(tbUserTemp);

        if(tbUserList.size()==0){
            throw new CustomException("用户名或密码错误",2003);
        }

        TbUser tbUserDb=tbUserList.get(0);

        //将用户输入的密码和数据库中的密码进行比对
        if (!SecurityUtils.matchesPassword(tbUser.getPwd(), tbUserDb.getPwd()))
        {
            throw new CustomException("用户名或密码错误",2003);
        }

        String token=cacheUserToRedis(tbUserDb);

        Map map=new HashMap();
        map.put("token",token);
        map.put("tbUser",tbUserDb);
        return map;
    }

    //缓存用户信息到redis中,返回token
    public String cacheUserToRedis(TbUser tbUser) {
        //置空密码
        tbUser.setPwd("");

        String token=jwtUtils.createToken(tbUser.getId());

        redisCache.setCacheObject(RedisConstants.RECEPTION_TOKEN_CONSTANT+tbUser.getId(),tbUser,RedisConstants.RECEPTION_TOKEN_TIMEOUT_CONSTANT, RedisConstants.RECEPTION_TOKEN_TIMEUNIT_CONSTANT);

        return token;
    }

    /**
     * 修改用户信息
     */
    @PostMapping("/updateUserInfo")
    public AjaxResult updateUserInfo(@RequestBody TbUser tbUser) {
        tbUser.setId(CurrentUserUtils.getCurrentUser().getId());
        tbUserService.updateTbUser(tbUser);
        return AjaxResult.success();
    }

    public String getDateStr(){
        Calendar cal = Calendar.getInstance();
        //日期格式化
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");//
        //获取最新的日期,
        Date date = new Date();
        //获取字符串格式的当天的日期
        String nowDate = sdf.format(date);  // 输出结果: 如:2021-03-31
        return nowDate;
    }

}
